home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / MATH / PI64KPAS / PI_64K.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-11-23  |  14.6 KB  |  522 lines

  1. {
  2.       A Program to compute Pi upto 65531 didgets (about 64k didgets)
  3.  
  4.                   "PI_64K.PAS"  by Mitchell Ross  [70324,241]  11-23-92
  5. Based on          "PIMUSIC.PAS" by Cino Hilliard  [72756,672]  10/10/87
  6. that was based on "pi2.pas"     by Chuck White    [75006,3677] May 4, 1986
  7. that was based on "pi1.pas"     by Cino Hilliard  [72756,672]  April 6, 1986
  8. that was based on "pi.pas"      by Cino Hilliard  [72756,672]  ???
  9.  
  10. -----------------------------------------------------------------------------
  11.                  Original Docs by Cino Hilliard Follow....
  12. -----------------------------------------------------------------------------
  13. this program computes the digits of pi using the arctangent formula
  14.  
  15.                 (  term 1  )   (  term 2  )
  16.     (1)  pi/4 := 4 arctan 1/5 - arctan 1/239
  17.  
  18.                                    in conjunction with the gregory series
  19.                      n
  20.     (2)  arctan x := sum [ (-1)^m*(2m + 1)^-1*x^(2m+1) ]  (approximately)
  21.                     m:=0
  22.  
  23. substituting into (1) and (2) the first few values of n, rearranging,
  24. simplyifing, and nesting  we have,
  25.  
  26. pi:= 3.2 + 1/25[-3.2/3 + 1/25[3.2/5 + 1/25[-3.2/7 + ...].].]       ( term 1 )
  27.     -1/239[4 +1/239^2[-4/3 +1/239^2[4/5 +1/239^2[-4/7 +...].].]   ( term 2 )
  28.  
  29. using the long division algorithm and some tricks i discovered, this
  30. ( nested ) infinite series can be used to calculate pi to a large
  31. number of decimal places in a reasonable amount of time.  a time
  32. function is included to show how slow things get when n is large.
  33.  
  34. improvements can be made by increasing the number of digits each array
  35. element holds and by changing the data type from integer to real for
  36. selected variables. of course the added number of digits these changes
  37. produce will cost much much more time. ah indeed, 'tis no free lunch!
  38. however, since term 1 and term 2 are computed seperately and since the
  39. arrays are step by step updated, the  program does lend itself to
  40. parallel or non von ( what a coincidence - see below )  processing.
  41.  
  42. for example, let computer 1 perform term 1 and computer 2 perform  term 2.
  43. moreover, let several computers share in the calculation of each
  44. of the individual terms. however, to keep each computer equally busy,
  45. a logarithmic type of adjustment must be made to decide on the number
  46. of terms to be assigned to each computer. since the higher power terms
  47. require much longer to compute, the computers assigned to higher powers
  48. must be given  fewer terms to do.
  49.  
  50. a little history
  51. ----------------
  52. in august, 1949, professor john von neumann used formulas  (1) and (2)
  53. to calculate pi to 2035 decimal places on the  eniac  computer.
  54. the effort was made to determine if the digits conformed to some type of
  55. pattern or if they were randomly distributed.
  56. the calculation was completed over the labor day weekend with the
  57. combined efforts of four eniac staff members working in eight-hour
  58. shifts to ensure continuous operation of the eniac. the calculation
  59. (including card handling time) took approximately 70 hours.
  60.  
  61. the conclusion was as suspected - the digits appeared to be random!
  62.  
  63. some years ago i requested information on pi from the encyclopedia
  64. britannica research service. i received a report giving the above
  65. historical account plus a listing of the 2035 digits.
  66.  
  67. a little comment
  68. ----------------
  69. using my t2k, pi1.pas computes pi to 2035 places in  15 min  31.97 sec.
  70.  
  71. gee whiz!  what earthly use can be made of this?  i plan to make designs
  72. and color patterns using the digit values as the basis. maybe something
  73. like fractals would be a good start. this is why computation and speed
  74. are important as i do not wish (nor trust) to key in entries from a
  75. published list.
  76.  
  77.                         cino hilliard
  78.                         [72756,672]
  79. -----------------------------------------------------------------------------
  80.                        End of original Docs...
  81. -----------------------------------------------------------------------------
  82.  
  83. My version in not in assembly, so that data types can easily by changed. The
  84. old program would only calc to a little over 2 thousand, so I decided to see
  85. just how many I could do. This program is the best I could do without going
  86. to a random disk file (S..L..O..W..!!!!) or to EMS (alas, beyond me). Because
  87. of the large compute times, I added a save/restore feature. Running this
  88. program at night, durring work hours, and on weekends on my home 386-25 took
  89. about 2 weeks to do the full 65531 didgets. I shudder to think what disk-based
  90. arrays would have done to the compute time. Well, here it is! If anyone can
  91. find a way to do more didgets, and still keep the speed up, please let me know.
  92.  
  93.              - Mitchell Ross
  94.                3670 Road 5-1
  95.                Delta, OH  43515      CI$: [70324,241]
  96. }
  97.  
  98. {$I-}       { no file IO      (speed...) }
  99. {$R-}       { no range checks (speed...) }
  100. {$S-}       { no stack checks (and more speed!) }
  101. {$N-} {$E-} { no co-processor, it's all integer math here }
  102.  
  103. Program CalcPi;
  104.  
  105. Uses CRT;
  106.  
  107. Const ArraySize = (64*1024)-2;         { as big as we can go... }
  108.       OutFileName = 'pi.!!!';         { final output file }
  109.  
  110.       SaveFileName1 = 'PI_WORK.$$1';      { save files }
  111.       SaveFileName2 = 'PI_WORK.$$2';
  112.  
  113. Type PiType = Array[0..ArraySize] of ShortInt;
  114.      PiPtrType = ^PiType;
  115.  
  116. var HowFar : Integer;
  117.     NumberToCalc : LongInt;                 { num of didgets }
  118.     j, q, v, r : LongInt;
  119.     Steps, Steps1, Steps2 : LongInt;
  120.     ArrayMax : LongInt;
  121.  
  122.     p,t,a : PiPtrType;               { here's the 3 BigNum arrays }
  123.  
  124. {---------------------------}
  125. { Handy to check for existing files. Don't leave home without it. }
  126. Function Exist( FileName : String ): Boolean;
  127.  
  128. Var WorkFile : Text;
  129.  
  130. Begin
  131.  {$I-}
  132.  Assign( WorkFile, FileName );
  133.  Reset( WorkFile );
  134.  If IOResult <> 0 then Exist := FALSE
  135.   ELSE begin
  136.    Exist := TRUE;
  137.   Close( WorkFile );
  138.  end;
  139. end;
  140.  
  141. {---------------------------}
  142. { saves _everything_ to disk, so we can pick up again later. }
  143. Procedure SaveSoFar;
  144.  
  145. Var SaveFile1 : Text;
  146.     SaveFile2 : File of PiType;
  147.  
  148. begin
  149.   Writeln;
  150.   Write('Saving...');
  151.  
  152.   Assign( SaveFile1, SaveFileName1 );
  153.   Rewrite( SaveFile1 );
  154.   Writeln( SaveFile1, ArrayMax );
  155.   Writeln( SaveFile1, HowFar );
  156.   Writeln( SaveFile1, NumberToCalc );
  157.   Writeln( SaveFile1, Steps );
  158.   Writeln( SaveFile1, Steps1 );
  159.   Writeln( SaveFile1, Steps2 );
  160.   Writeln( SaveFile1, j );
  161.   Writeln( SaveFile1, q );
  162.   Writeln( SaveFile1, v );
  163.   Writeln( SaveFile1, r );
  164.   Close( SaveFile1 );
  165.  
  166.   Assign( SaveFile2, SaveFileName2 );
  167.   Rewrite( SaveFile2 );
  168.   Write( SaveFile2, a^ );
  169.   Write( SaveFile2, p^ );
  170.   Write( SaveFile2, t^ );
  171.   Close( SaveFile2 );
  172.   Writeln('Done!');
  173. end;
  174.  
  175. {---------------------------}
  176. { and load it back again.... }
  177. Procedure RestoreSoFar;
  178.  
  179. Var SaveFile1 : Text;
  180.     SaveFile2 : File of PiType;
  181.  
  182. begin
  183.   Writeln;
  184.   Write('Restoring...');
  185.  
  186.   Assign( SaveFile1, SaveFileName1 );
  187.   Reset( SaveFile1 );
  188.   Readln( SaveFile1, ArrayMax );
  189.   Readln( SaveFile1, HowFar );
  190.   Readln( SaveFile1, NumberToCalc );
  191.   Readln( SaveFile1, Steps );
  192.   Readln( SaveFile1, Steps1 );
  193.   Readln( SaveFile1, Steps2 );
  194.   Readln( SaveFile1, j );
  195.   Readln( SaveFile1, q );
  196.   Readln( SaveFile1, v );
  197.   Readln( SaveFile1, r );
  198.   Close( SaveFile1 );
  199.  
  200.   Assign( SaveFile2, SaveFileName2 );
  201.   Reset( SaveFile2 );
  202.   Read( SaveFile2, a^ );
  203.   Read( SaveFile2, p^ );
  204.   Read( SaveFile2, t^ );
  205.   Close( SaveFile2 );
  206.   Writeln('Done!');
  207. end;
  208.  
  209. {---------------------------}
  210. Procedure CheckForQuit;
  211.  
  212. Var Key : Char;
  213.  
  214. begin
  215.   Key := '▒';         { my favorite char, but just make it <> #27 }
  216.  
  217.   While KeyPressed do   Key := ReadKey;          { clear buffer }
  218.  
  219.   If Key = #27 then begin            { if escape pressed, save }
  220.     SaveSoFar;
  221.     HALT;
  222.   end;
  223. end;
  224.  
  225. {---------------------------}         { real guts of the program follow... }
  226. {---------------------------}
  227. procedure div_32_by_Steps_to_a;  { divide 3.2 by Steps and store in array a }
  228.  
  229. begin
  230.  q := (3 div Steps);
  231.  r := (3 mod Steps);
  232.  a^[0]:= q;
  233.  v := r * 10 + 2;
  234.  q := (v div Steps);
  235.  r := (v mod Steps);
  236.  a^[1] := q;
  237.  
  238.  for j:= 2 to ArrayMax do begin
  239.    v := r * 10;
  240.    q := (v div Steps);
  241.    r := (v mod Steps);
  242.    a^[j] := q;
  243.  end;
  244. end;
  245.  
  246. {---------------------------}
  247. procedure diva(d:integer); { divide a by specified integer  }
  248.  
  249. begin
  250.   r := 0;
  251.   for j := 0 to ArrayMax do begin
  252.     v := r * 10 + a^[j];
  253.     q := (v div d);
  254.     r := (v mod d);
  255.     a^[j] := q;
  256.   end;
  257. end;
  258.  
  259. {---------------------------}
  260. procedure div_4_by_Steps_into_a;   { divide 4 by Steps and store in a }
  261.  
  262. begin
  263.   q := (4 div Steps);
  264.   r := (4 mod Steps);
  265.   a^[0] := q;
  266.   for j := 2 to ArrayMax do begin
  267.     v := r * 10;
  268.     q := (v div Steps);
  269.     r := (v mod Steps);
  270.     a^[j] := q;
  271.   end;
  272. end;
  273.  
  274. {---------------------------}
  275. procedure div_32_by_Steps_into_p;  { divide 3.2 by Steps and store in p }
  276.  
  277. begin
  278.   q := (3 div Steps);
  279.   r := (3 mod Steps);
  280.   p^[0] := q;
  281.   v := r * 10 + 2;
  282.   q := (v div Steps);
  283.   r := (v mod Steps);
  284.   p^[1] := q;
  285.   for j := 2 to ArrayMax do begin
  286.     v := r * 10;
  287.     q := (v div Steps);
  288.     r := (v mod Steps);
  289.     p^[j] := q;
  290.   end;
  291. end;
  292.  
  293. {---------------------------}
  294. procedure div_4_by_Steps_into_p;   { divide 4 by Steps and store in p }
  295.  
  296. begin
  297.   q := (4 div Steps);
  298.   r := (4 mod Steps);
  299.   p^[0] := q;
  300.   for j := 1 to ArrayMax do begin
  301.     v := r * 10;
  302.     q := (v div Steps);
  303.     r := (v mod Steps);
  304.     p^[j] := q;
  305.   end;
  306. end;
  307.  
  308. {---------------------------}
  309. procedure suba;         { subtract a from p  and store in a }
  310.  
  311. begin
  312.   for j := ArrayMax downto 0 do begin
  313.     a^[j] := p^[j] - a^[j];
  314.   end;
  315. end;
  316.  
  317. {---------------------------}
  318. procedure sub32a;        { subtract a from 3.2 and store in t }
  319.  
  320. begin
  321.   t^[0] := 3;
  322.   t^[1] := 1;
  323.   for j := ArrayMax downto 2 do begin
  324.     t^[j] := 9-a^[j];
  325.   end;
  326. end;
  327.  
  328. {---------------------------}
  329. procedure sub4a;        { subtract a from 4 and store in a }
  330.  
  331. begin
  332.   a^[0] := 3;
  333.  
  334.   for j := ArrayMax downto 1 do begin
  335.     a^[j] := 9-a^[j];
  336.   end;
  337. end;
  338.  
  339. {---------------------------}
  340. procedure subt;         { subtract term2 from term 1 and store in a }
  341.  
  342. begin
  343.   for j := ArrayMax downto 1 do begin
  344.     a^[j] := t^[j] - a^[j];
  345.  
  346.     while a^[j] < 0 do begin
  347.       a^[j] := a^[j] + 10;
  348.       a^[j-1] := a^[j-1] + 1;
  349.     end;
  350.  
  351.     while a^[j] > 9 do begin
  352.       a^[j] := a^[j] - 10;
  353.       a^[j-1] := a^[j-1] - 1;
  354.     end;
  355.  
  356.   end;
  357. end;
  358.  
  359. {---------------------------}
  360. procedure compute_a1;
  361.  
  362. begin
  363.   CheckForQuit;               { give user chance to save work }
  364.   Steps := Steps1;           { compute term 1 to Steps1 div 2  places }
  365.   div_32_by_Steps_to_a;
  366.   diva(25);
  367.   HowFar := 1;
  368.   CheckForQuit;               { give user chance to save work }
  369. end;
  370.  
  371. {---------------------------}
  372. procedure compute_a2;
  373.  
  374. begin
  375.   while Steps > 3 do begin
  376.     CheckForQuit;               { give user chance to save work }
  377.     GotoXY(1,WhereY-1);
  378.     Writeln( 'Pass 1:  ', Steps,' of ',Steps1,'  ');   { show progress }
  379.     Steps := Steps -2;
  380.     div_32_by_Steps_into_p;
  381.     suba;
  382.     diva(25);
  383.   end;
  384.   HowFar := 2;
  385.   CheckForQuit;               { give user chance to save work }
  386. end;
  387.  
  388. {---------------------------}
  389. procedure compute_a3;
  390.  
  391. begin
  392.   sub32a;
  393.   HowFar := 3;
  394.   CheckForQuit;               { give user chance to save work }
  395. end;
  396.  
  397. {---------------------------}
  398. procedure compute_b1;
  399.  
  400. begin
  401.   Writeln;
  402.   Steps := Steps2;          { compute term 2 to Steps2 div 2 places }
  403.   div_4_by_Steps_into_a;
  404.   diva(239);
  405.   diva(239);
  406.   HowFar := 4;
  407.   CheckForQuit;               { give user chance to save work }
  408. end;
  409.  
  410. {---------------------------}
  411. procedure compute_b2;
  412.  
  413. begin
  414.   while Steps > 3 do begin
  415.     CheckForQuit;               { give user chance to save work }
  416.     GotoXY(1,WhereY-1);
  417.     Writeln(  'Pass 2:  ', Steps,' of ',Steps2,'  ');  { show progress }
  418.     Steps := Steps -2;
  419.     div_4_by_Steps_into_p;
  420.     suba;
  421.     diva(239);
  422.     diva(239);
  423.   end;
  424.   HowFar := 5;
  425.   CheckForQuit;               { give user chance to save work }
  426. end;
  427.  
  428. {---------------------------}
  429. procedure compute;      { compute the nested series for Steps1 iterations }
  430.  
  431. begin
  432.   If HowFar <= 0 then  compute_a1;          { if we did it before, don't }
  433.   If HowFar <= 1 then  compute_a2;          { do it again.               }
  434.   If HowFar <= 2 then  compute_a3;
  435.  
  436.   If HowFar <= 3 then  compute_b1;
  437.   If HowFar <= 4 then  compute_b2;
  438.  
  439.   sub4a;
  440.   diva(239);
  441.   subt;                 { subtract term 2 from term 1 and store in a }
  442. end;
  443.  
  444. {---------------------------}
  445. procedure printpi;    { print the  formated digits of pi }
  446.  
  447. Var OutFile : Text;
  448.     z : Integer;
  449.  
  450. begin
  451.   Writeln('░▒▓█ DONE! Saving.... █▓▒░');
  452.   Assign( OutFile, OutFileName );
  453.   Rewrite( OutFile );
  454.  
  455.   write( OutFile, 'π = 3.');
  456.   for j:=1 to NumberToCalc do begin
  457.     write( OutFile, a^[j]);
  458.     if j mod 5 = 0 then write( OutFile, ' ');
  459.     if j mod 50= 0 then writeln( OutFile, ' ',j:4,' pl');
  460.   end;
  461.   writeln( OutFile );
  462.   writeln;
  463.   writeln('  Results saved to ',OutFileName );
  464.   writeln;
  465.  
  466.   Close( OutFile );
  467.  
  468.   {$I-}
  469.   Assign( OutFile, SaveFileName1 );          { done now, kill temp files }
  470.   Erase( OutFile );
  471.   Assign( OutFile, SaveFileName2 );
  472.   Erase( OutFile );
  473.   z := IOResult;          { throw away any errors }
  474. end;
  475.  
  476. {---------------------------}
  477. procedure start;               { prompt for input and initialize }
  478.  
  479. begin
  480.    HowFar := 0;
  481.  
  482.    If Exist( SaveFileName1 ) then begin
  483.      Writeln('------ Restoring from saved session -----');
  484.      RestoreSoFar;
  485.    end ELSE begin
  486.      write('Number decimal places? (25..',ArraySize-3,') :');
  487.      readln(NumberToCalc);
  488.      Writeln;
  489.  
  490.      ArrayMax  := NumberToCalc+2;
  491.      Steps1 := 4*(3*ArrayMax div 8)+3;   { number of terms- series 1 }
  492.      Steps2 := 4*(Steps1 div 14)+3;      { number of terms- series 2 }
  493.    end;
  494.   Writeln;
  495.   Writeln('Press ESC to save work so far. (Might take a moment after keypress)');
  496. end;
  497.  
  498. {-----------------------}
  499. {-----------------------}
  500.  
  501. var z : Integer;
  502.  
  503. begin
  504.   ClrScr;
  505.   Writeln('╔═════════════════════════════════════════════════╗');
  506.   Writeln('║ Pi_64k - By Mitchell Ross                       ║');
  507.   Writeln('║             3670 Road 5-1                       ║');
  508.   Writeln('║             Delta, OH  43515   CI$: [70324,241] ║');
  509.   Writeln('║                                                 ║');
  510.   Writeln('║   Compute the value of PI, up to 64k didgets    ║');
  511.   Writeln('╚═════════════════════════════════════════════════╝');
  512.   Writeln;
  513.  
  514.   New( a );
  515.   New( p );
  516.   New( t );
  517.  
  518.   start;
  519.   compute;
  520.   printpi;
  521. end.
  522.